using GameMain.Utils;
using HybridCLR.Editor;
using HybridCLR.Editor.Installer;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;

namespace GameMain.Editor.BuildPipeline
{
    public partial class BuildPipeline
    {
        [MenuItem("HCLRExtTools/CheckHybridCLRInstall", false, 0)]
        public static void CheckHybridCLRInstall()
        {
            SimpleLog.Log($"[BuildPipeline::InstallDefaultHybridCLR] 开始检查插件状态");
            var localHclrVersion = EditorPrefs.GetString("[CustomBuildPipeline]installed_hclr_version");
            var HclrInstaller = new InstallerController();
            if (!string.IsNullOrEmpty(localHclrVersion) && localHclrVersion == HclrInstaller.PackageVersion.Trim() && HclrInstaller.HasInstalledHybridCLR())
            {
                SimpleLog.Log($"[BuildPipeline::InstallDefaultHybridCLR] 无需安装插件");
            }
            else
            {
                SimpleLog.Log($"[BuildPipeline::InstallDefaultHybridCLR] 开始安装插件");
                EditorUtility.DisplayProgressBar("正在安装插件...", "", 0);
                HclrInstaller.InstallDefaultHybridCLR();
                EditorPrefs.SetString("[CustomBuildPipeline]installed_hclr_version", HclrInstaller.PackageVersion.Trim());

                SimpleLog.Log($"[BuildPipeline::InstallDefaultHybridCLR] 安装插件完成");
            }

            PatchCppCode();

            EditorUtility.ClearProgressBar();
        }

        private static void PatchCppCode()
        {
            SimpleLog.Log($"[BuildPipeline::PatchCppCode] patch开始");

            var assets = AssetDatabase.FindAssets("LibIl2cppModule-2021");
            if (assets.Length == 0)
            {
                throw new Exception($"[BuildPipeline::PatchCppCode] LibIl2cppModule-2021!!!");
            }

            var filePath = AssetDatabase.GUIDToAssetPath(assets[0]);
            var dst = Path.Combine(SettingsUtil.LocalIl2CppDir, "libil2cpp", "utils", "HCLRExtTools");
            var dirInfo = new DirectoryInfo(dst);
            if (dirInfo.Exists)
            {
                dirInfo.Delete(true);
            }
            dirInfo.Create();

            if (!ExtractApiCodeToPath(filePath, dst))
            {
                throw new Exception($"[BuildPipeline::PatchCppCode] 释放LibIl2cppModule-2021出错");
            }

            var metadataModuleCpp = Path.Combine(SettingsUtil.LocalIl2CppDir, "libil2cpp", "hybridclr", "metadata", "MetadataModule.cpp");
            var allLines = File.ReadAllLines(metadataModuleCpp);
            var outLines = new List<string>();
            outLines.Add(@"#include ""utils/HCLRExtTools/HCLRExtTools.h""");
            var callIdx = 0;
            foreach (var line in allLines)
            {
                if (line.Contains("HCLRExtTools.h"))
                {
                    continue;
                }

                if (line.Contains("HCLRExtTools::RuntimeApi::RegisterInternalCalls()"))
                {
                    continue;
                }

                if (line.Contains("MetadataModule::Initialize"))
                {
                    callIdx = outLines.Count + 2;
                }

                outLines.Add(line.TrimEnd());
            }
            outLines.Insert(callIdx, "        HCLRExtTools::RuntimeApi::RegisterInternalCalls();");

            File.WriteAllLines(metadataModuleCpp, outLines);

            metadataModuleCpp = Path.Combine(SettingsUtil.LocalIl2CppDir, "libil2cpp", "vm", "GlobalMetadata.cpp"); 
            allLines = File.ReadAllLines(metadataModuleCpp);
            outLines.Clear();
            foreach (var line in allLines)
            {
                var nl = line.TrimEnd();
                if (nl.Contains("s_GlobalMetadataHeader->sanity =="))
                {
                    nl = "// IL2CPP_ASSERT(s_GlobalMetadataHeader->sanity == 0xFAB11BAF);";
                }
                else if (nl.Contains("s_GlobalMetadataHeader->version =="))
                {
                    nl = "// IL2CPP_ASSERT(s_GlobalMetadataHeader->version == 29);";
                }
                outLines.Add(nl);
            }
            File.WriteAllLines(metadataModuleCpp, outLines);

            SimpleLog.Log($"[BuildPipeline::PatchCppCode] patch结束");
        }
    }
}
